import React, { useEffect, useState, useMemo } from 'react'
import { Select, Divider, Pagination, Spin, message } from 'antd'
const { Option } = Select
import { useDebounce } from 'react-use'
import qs from 'qs'
import './SearchSelect.css'
import { SearchOutlined } from '@ant-design/icons'

export default ({
                  axios,
                  url = '',
                  queryParams = {},
                  queryKeyName = 'queryKeyword',
                  pageSize = 10,
                  pageSizeKeyName = 'pageSize',
                  currentPageKeyName = 'curPage',
                  responseCurrentPageName = currentPageKeyName,

                  labelKeyName = 'label',
                  valueKeyName = 'value',
                  disabledKeyName = 'disabled',

                  responseTotalRowsKeyName = 'totalRows',
                  flagKeyName = 'flag',
                  responseDataKeyName = 'data',
                  listKeyName = 'dataList',
                  flagValue = 1,
                  mode,
                  placeholder = '请输入关键字',
                  allowClear = true,
                  startSearchIndex = 0, // 自定义接口搜索起始索引
                  qsStringify,
                  selectStyle = {},
                  dropdownStyle = {},
                  extraSuffix = () => {},
                  value,
                  onChange = () => {},
                  max = 999,
                  lang = 'zh',
                  renderOptions = null,
                  responseDataFormat = data => data,
                  selectProps = {},
                  selectedOptionList = [],
                  ...otherProps
                }) => {
  const [searchText, setSearchText] = useState('') // 搜索文本，防抖用
  const [list, setList] = useState([{ value: '987', label: '11111', text: '11111' }]) // 列表
  const [paginationData, setPaginationData] = useState({
    current: 1, // 当前页
    pageSize: pageSize, // 分页大小
    total: 0 // 总条数
  })
  const [totalPage, setTotalPage] = useState(0)
  const [loading, setLoading] = useState(false)
  const difference = 1 - startSearchIndex // pagination.current - startSearchIndex，前端分页起始值与后端搜索起始值的差值
  const [selectValue, setSelectValue] = useState()
  // const [isPaging, setIsPaging] = useState(true) // 接口是否分页

  // 根据value回显
  useEffect(() => {
    if (value === undefined) return
    const fetchData = () => {
      const newVal = Array.isArray(value) ? value.map(d => d.toString()) : value.toString()
      const newValDataType = Object.prototype.toString.call(newVal)
      const selectValueDataType = Object.prototype.toString.call(selectValue)

      const newValMap = {}
      for (const item of newVal) {
        newValMap[item] = item
      }

      let flag = true
      if (newValDataType === '[object Array]' && selectValueDataType === '[object Array]') {
        for (const item of selectValue) {
          if (!newValMap[item]) {
            flag = false
            break
          }
        }
      } else {
        flag = newVal !== selectValue
      }

      if (flag) {
        getList().then(() => {
          setSelectValue(newVal)
        })
      }
    }
    fetchData()
  }, [value])

  const formatList = (arr = []) => {
    // 合并数据
    const hash = {}
    const newList = [...arr, ...selectedOptionList].reduce((total, currentValue) => {
      const value = currentValue.value.toString()
      if (hash[value]) {
        // 如果当前元素的key值没有在hash对象里，则可放入最终结果数组
        total.forEach((item, index) => {
          if (item.value === value) {
            total[index] = { ...item, ...currentValue, value }
          }
        })
      } else {
        hash[value] = 1 // 把当前元素key值添加到hash对象
        total.push({ ...currentValue, value }) // 把当前元素放入结果数组
      }
      return total // 返回结果数组
    }, [])
    setList(newList)
  }

  const getList = async(value, paginationParams = {}) => {
    setLoading(true)
    // 整合入参
    const searchData = {
      ...queryParams,
      [currentPageKeyName]: (paginationParams.current - difference || paginationParams.current - difference === 0) ? paginationParams.current - difference : paginationData.current - difference,
      [pageSizeKeyName]: paginationParams.pageSize || paginationData.pageSize,
      [queryKeyName]: value
    }
    // 是否使用qs模块序列化入参
    const params = qsStringify ? qs.stringify(searchData) : searchData
    const resData = await axios.post(url, params).catch((error) => {
      setLoading(false)
      console.error(error)
    })
    // 用户自定义修改相应数据
    const formatData = responseDataFormat(resData)
    // 解构响应数据
    const { [flagKeyName]: flag, [responseDataKeyName]: data = {}, [responseDataKeyName]: { [listKeyName]: dataList = [], [responseTotalRowsKeyName]: totalRows, [responseCurrentPageName]: curPage } = {}} = formatData
    if (flag === flagValue) {
      // 获取总页数
      setTotalPage(Math.ceil(totalRows / pageSize))
      // 设置新的分页数据
      setPaginationData({
        ...paginationData,
        current: curPage + difference,
        total: totalRows
      })
      formatList(dataList)
      // setList(dataList)
    }
    setLoading(false)
  }

  // 搜索
  const handleSearch = (value) => {
    setSearchText(value)
  }

  // 选中后，处理多选、单选
  const handleChange = (value, selectedOptions) => {
    const selectedRows = selectedOptions.map(item => item.row)
    let selectedList
    let selectedValue
    // 多选
    if (Array.isArray(value) && ['tags', 'multiple'].includes(mode) && value.length > max) { // 多选，并且超过多大值，删除多余的
      value.slice(0, max)
      selectedRows.slice(0, max)
      message.warning(`最多可选${max}个`)
    } else { // 单选、多选时不超过直接赋值获取
      selectedList = selectedRows
      selectedValue = value
      setSelectValue(selectedValue)
      onChange(selectedValue, selectedList)
    }
  }

  const handleFocus = () => {
    // !selectValue &&
    // getList({
    //   [queryKeyName]: ''
    // })
    // otherProps.onFocus?.()
  }

  // 防抖
  useDebounce(
    () => {
      getList(searchText)
    },
    300,
    [searchText]
  )

  // 下拉框
  const renderHtmlOptions = useMemo(() => {
    if (renderOptions) {
      return renderOptions(list)
    } else {
      return list.map((item, index) => {
        const extraLabel = extraSuffix(item)
        return <Option
          disabled={item[disabledKeyName]}
          key={item[valueKeyName] || `${index}-${paginationData[currentPageKeyName]}`}
          value={item[valueKeyName]}
          label={item[labelKeyName]}
          row={item}
        >
          <div style={{ display: 'flex', justifyContent: 'space-between' }}>
            <span className='option-label' title={item[labelKeyName]}>{item[labelKeyName]}</span>
            {
              extraLabel &&
              <span className='option-extra-label' title={extraLabel}>{extraLabel}</span>
            }
          </div>
        </Option>
      })
    }
  }, [list, renderOptions])

  // 分页
  const dropdownRender = (menu) => {
    return (
      <>
        {totalPage > 1 ? (
          <div
            style={{
              display: 'flex',
              padding: '0 5px 5px',
              justifyContent: 'flex-end'
            }}
          >
            <Pagination
              simple
              size='small'
              total={paginationData.total}
              pageSize={paginationData.pageSize}
              current={paginationData.current}
              onChange={(current, pageSize) => {
                getList(searchText, { current })
              }}
            />
          </div>
        ) : null}
        <Divider style={{ margin: 0 }} />
        {menu}
      </>
    )
  }

  // loading & 当下拉列表为空时显示的内容
  const notFoundContent = () => {
    return (
      loading ? <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}><Spin size='small' /></div>
        : <div role='listbox' id='rc_select_0_list' className='ant-select-item-empty'>
          <div className='ant-empty ant-empty-normal ant-empty-small'>
            <div className='ant-empty-image'>
              <svg className='ant-empty-img-simple' width='64' height='41' viewBox='0 0 64 41'
                   xmlns='http://www.w3.org/2000/svg'>
                <g transform='translate(0 1)' fill='none' fillRule='evenodd'>
                  <ellipse className='ant-empty-img-simple-ellipse' cx='32' cy='33' rx='32' ry='7' />
                  <g className='ant-empty-img-simple-g' fillRule='nonzero'>
                    <path
                      d='M55 12.76L44.854 1.258C44.367.474 43.656 0 42.907 0H21.093c-.749 0-1.46.474-1.947 1.257L9 12.761V22h46v-9.24z' />
                    <path
                      d='M41.613 15.931c0-1.605.994-2.93 2.227-2.931H55v18.137C55 33.26 53.68 35 52.05 35h-40.1C10.32 35 9 33.259 9 31.137V13h11.16c1.233 0 2.227 1.323 2.227 2.928v.022c0 1.605 1.005 2.901 2.237 2.901h14.752c1.232 0 2.237-1.308 2.237-2.913v-.007z'
                      className='ant-empty-img-simple-path' />
                  </g>
                </g>
              </svg>
            </div>
            <div className='ant-empty-description'>暂无数据</div>
          </div>
        </div>
    )
  }

  return (
    <>
      <Select
        {...selectProps}
        showSearch
        suffixIcon={<SearchOutlined />}
        placeholder={placeholder}
        allowClear={allowClear}
        mode={mode}
        notFoundContent={notFoundContent()}
        getPopupContainer={(triggerNode) => triggerNode.parentElement}
        dropdownRender={dropdownRender}
        onSearch={handleSearch}
        onChange={handleChange}
        onFocus={handleFocus}
        value={selectValue}
        style={{
          ...selectStyle
        }}
        dropdownStyle={{
          ...dropdownStyle
        }}
      >
        {renderHtmlOptions}
      </Select>
      <style jsx>{`
        .option-label {
          overflow: hidden;
          text-overflow: ellipsis;
          white-space: nowrap;
        }
      `}</style>
    </>
  )
}
